home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / visulztn / saoimage / saoimage.lha / crdset.c < prev    next >
C/C++ Source or Header  |  1990-04-20  |  12KB  |  361 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    crdset.c (Coordinate Set)
  6.  * Purpose:    Set up coordinate system parameters and translation matrices
  7.  * Subroutine:    set_coordsys()        returns: void
  8.  * Subroutine:    set_transform()        returns: void
  9.  * Subroutine:    set_imgtran()        returns: void
  10.  * Subroutine:    set_fbuftran()        returns: void
  11.  * Subroutine:    set_buftran()        returns: void
  12.  * Subroutine:    set_edges()        returns: void
  13.  * Xlib calls:    none
  14.  * Notes:
  15.  *  the base coordinate system is the img
  16.  *  coordinate conversions are computed by passing through the img
  17.  *  the img has 0.0, 0.0 as its upper left corner
  18.  *  files often have 0.5,0.5 at lower left corner (index from 1, ioff = 0.0)
  19.  *  disp, buffer, and pan have 0.0,0.0 in upper left corner (ioff = 0.5)
  20.  *  integer values refer to the center of the pixel in its coordinate system
  21.  *  translations always produce a real (float) value output
  22.  * Copyright:    1988 Smithsonian Astrophysical Observatory
  23.  *        You may do anything you like with this file except remove
  24.  *        this copyright.  The Smithsonian Astrophysical Observatory
  25.  *        makes no representations about the suitability of this
  26.  *        software for any purpose.  It is provided "as is" without
  27.  *        express or implied warranty.
  28.  * Modified:    {0} Michael VanHilst    initial version         1 September 1988
  29.  *        {1} MVH support for file buffer coord sys      19 Feb 1990
  30.  *        {n} <who> -- <does what> -- <when>
  31.  */
  32.  
  33. #include "hfiles/coord.h"        /* coord structs */
  34. #include "hfiles/image.h"        /* image struct */
  35.  
  36. /*
  37.  * Subroutine:    set_coordsys
  38.  * Purpose:    Set basic params for a coordinate system
  39.  */
  40. void set_coordsys ( csys, ioff, width, height, x1, y1, x2, y2 )
  41.      Coordsys *csys;
  42.      double ioff;
  43.      int width, height;
  44.      int x1, y1, x2, y2;
  45. {
  46.   csys->width = width;
  47.   csys->height = height;
  48.   csys->ioff = ioff;
  49.   /* pixel coords of four sides (col or row just inside the edge) */
  50.   csys->X1i = x1;
  51.   csys->Y1i = y1;
  52.   csys->X2i = x2;
  53.   csys->Y2i = y2;
  54.   csys->Xwdth = 1 + x2 - x1;
  55.   csys->Yhght = 1 + y2 - y1;
  56.   /* put the center in the center of the pixel before the true center */
  57.   csys->cenX = (float)(x1 + ((csys->Xwdth - 1) / 2)) + ioff;
  58.   csys->cenY = (float)(y1 + ((csys->Yhght - 1) / 2)) + ioff;
  59.   /* determine real coords of outer edge using ... */
  60.   /* ... offset from integer coords to real coords */
  61.   if( ioff < 0.25 ) {
  62.     csys->X1 = (float)x1 - (float)0.5;
  63.     csys->Y1 = (float)y1 - (float)0.5;
  64.     csys->X2 = (float)x2 + (float)0.5;
  65.     csys->Y2 = (float)y2 + (float)0.5;
  66.   } else {
  67.     csys->X1 = (float)x1;
  68.     csys->Y1 = (float)y1;
  69.     csys->X2 = (float)(x2 + 1);
  70.     csys->Y2 = (float)(y2 + 1);
  71.   }
  72. }
  73.  
  74. /*
  75.  * Subroutine:    set_transform
  76.  * Purpose:    Calculate transforms given where to put A on B
  77.  * Note:    Forward transform is A to B
  78.  */
  79. void set_transform ( BAcenX, BAcenY, BAzoom, Asys, Bsys, AtoB, BtoA )
  80.      double BAcenX, BAcenY;    /* i: B coords of center of A system */
  81.      double BAzoom;        /* i: size of a B pixel in A units */
  82.      Coordsys *Asys, *Bsys;
  83.      Transform *AtoB, *BtoA;
  84. {
  85.   float ABzoom;
  86.   void set_trans_speed(), invert_transform();
  87.  
  88.   ABzoom = 1.0 / BAzoom;
  89.   AtoB->inx_outx = ABzoom;
  90.   AtoB->iny_outx = 0.0;
  91.   AtoB->add_outx = BAcenX - (Asys->cenX * ABzoom);
  92.   /* if given an integer parameter, its float value would be less by ioff */
  93.   AtoB->iadd_outx = BAcenX - ((Asys->cenX - Asys->ioff) * ABzoom);
  94.   AtoB->inx_outy = 0.0;
  95.   AtoB->iny_outy = ABzoom;
  96.   AtoB->add_outy = BAcenY - (Asys->cenY * ABzoom);
  97.   AtoB->iadd_outy = BAcenY - ((Asys->cenY - Asys->ioff) * ABzoom);
  98.   /* compute speedy integer computation parameters */
  99.   set_trans_speed(AtoB);
  100.   /* compute the inverse parameters (complete) */
  101.   invert_transform(BtoA, AtoB, Bsys->ioff); 
  102. }
  103.  
  104. /*
  105.  * Subroutine:    set_imgtran
  106.  * Purpose:    Set the img-to-file transform
  107.  */
  108. void set_imgtran ( image, img, file, imgtofile, filetoimg )
  109.      struct imageRec *image;
  110.      Coordsys *img, *file;
  111.      Transform *imgtofile, *filetoimg;
  112. {
  113.   float if_zoom;
  114.   void rotate_transform(), set_trans_speed(), invert_transform();
  115.  
  116.   if_zoom = 1.0 / image->fiblock;
  117.   imgtofile->inx_outx = if_zoom;
  118.   imgtofile->iny_outx = 0.0;
  119.   imgtofile->add_outx = image->ficenX - (img->cenX * if_zoom);
  120.   /* if given an integer parameter, its float value would be less by ioff */
  121.   imgtofile->iadd_outx = image->ficenX - ((img->cenX - img->ioff) * if_zoom);
  122.   imgtofile->inx_outy = 0.0;
  123.   imgtofile->iny_outy = if_zoom;
  124.   imgtofile->add_outy = image->ficenY - (img->cenY * if_zoom);
  125.   imgtofile->iadd_outy = image->ficenY - ((img->cenY - img->ioff) * if_zoom);
  126.   /* if rotation or y coordinate flipping is to be applied, do it new */
  127.   if( (image->rotate_code != 0) || (image->row_order != 0) ) {
  128.     rotate_transform(img, imgtofile, image->row_order, image->rotate_code);
  129.   }
  130.   /* compute speedy integer computation parameters */
  131.   set_trans_speed(imgtofile);
  132.   /* compute the inverse parameters (complete) */
  133.   invert_transform(filetoimg, imgtofile, file->ioff);
  134. }
  135.  
  136. /*
  137.  * Subroutine:    set_fbuftran
  138.  * Purpose:    Set buffer-to-filebuffer transform, should the
  139.  *        two buffers differ.
  140.  * Note:    Two buffers have same dimensions (and are usually the same)
  141.  */
  142. void set_fbuftran ( image, buf, fbuf, buftofbuf )
  143.      struct imageRec *image;
  144.      Coordsys *buf, *fbuf;    /* descriptions of short and file buffers */
  145.      Transform *buftofbuf;
  146. {
  147.   void rotate_transform(), set_trans_speed();
  148.  
  149.   buftofbuf->inx_outx = 1.0;
  150.   buftofbuf->iny_outx = 0.0;
  151.   buftofbuf->add_outx = 0.0;
  152.   buftofbuf->iadd_outx = 0.5;
  153.   buftofbuf->inx_outy = 0.0;
  154.   buftofbuf->iny_outy = 1.0;
  155.   buftofbuf->add_outy = 0.0;
  156.   buftofbuf->iadd_outy = 0.5;
  157.   /* if rotation or y coordinate flipping is to be applied, do it new */
  158.   if( (image->rotate_code != 0) || (image->row_order != 0) ) {
  159.     rotate_transform(buf, buftofbuf, image->row_order, image->rotate_code);
  160.   }
  161.   /* compute speedy integer computation parameters */
  162.   set_trans_speed(buftofbuf);
  163.   /* set the fbuf coordinate system parameters */
  164.   if( image->rotate_code & 1 ) {
  165.     /* rotated 90 or 270 degrees means switch X and Y axes */
  166.     fbuf->X1 = buf->Y1;
  167.     fbuf->X2 = buf->Y2;
  168.     fbuf->Y1 = buf->X1;
  169.     fbuf->Y2 = buf->X2;
  170.     fbuf->X1i = buf->Y1i;
  171.     fbuf->X2i = buf->Y2i;
  172.     fbuf->Y1i = buf->X1i;
  173.     fbuf->Y2i = buf->X2i;
  174.     fbuf->Xwdth = buf->Yhght;
  175.     fbuf->Yhght = buf->Xwdth;
  176.     fbuf->cenX = buf->cenY;
  177.     fbuf->cenY = buf->cenX;
  178.     fbuf->width = buf->height;
  179.     fbuf->height = buf->width;
  180.     fbuf->ioff = buf->ioff;
  181.   } else
  182.     bcopy((char *)buf, (char *)fbuf, sizeof(Coordsys));
  183. }
  184.  
  185. /*
  186.  * Subroutine:    set_buftran
  187.  * Purpose:    Set buffer-to-img transform (& buf-to-file)
  188.  * Note:    adjusts alignment so as not to waste buffer space
  189.  * Note:    edges later used to check whether requested display is
  190.  *        available
  191.  * Exception:    assumes buf is not smaller than disp
  192.  */
  193. void set_buftran ( coord )
  194.      struct coordRec *coord;
  195. {
  196.   void set_transform(), combine_transform(), set_edges(), invert_transform();
  197.  
  198.   /* if buf and image are identical, just copy */
  199.   if( !coord->bufcheck ) {
  200.     set_transform(coord->img.cenX, coord->img.cenY, 1.0,
  201.           &coord->buf, &coord->img,
  202.           &coord->buftoimg, &coord->imgtobuf);
  203.     bcopy((char *)&(coord->imgtofile),
  204.       (char *)&(coord->buftofile), sizeof(Transform));
  205.     coord->ib.srcX1 = 0;
  206.     coord->ib.srcX2 = coord->img.width - 1;
  207.     coord->ib.srcY1 = 0;
  208.     coord->ib.srcY2 = coord->img.height - 1;
  209.     coord->ib.srcXwdth = coord->img.width;
  210.     coord->ib.srcYhght = coord->img.height;
  211.     coord->ib.cenX = coord->img.cenX;
  212.     coord->ib.cenY = coord->img.cenY;
  213.     coord->ib.zoom = 1.0;
  214.     coord->ib.block = 1;
  215.   } else {
  216.     float lX, tY, rX, bY, diff;
  217.     {
  218.       register double ibzoom;
  219.  
  220.       /* if the buffer needs checking, calculate buffer to img zoom */
  221.       if( (coord->buf.width < ((double)coord->disp.width /
  222.                    coord->id.zoom)) ||
  223.      (coord->buf.height < ((double)coord->disp.height /
  224.                    coord->id.zoom)) ) {
  225.     /* use idzoom if zoom 1 won't work (check disp size in img coords) */
  226.     ibzoom = coord->id.zoom;
  227.     coord->ib.block = coord->id.block;
  228.       } else {
  229.     ibzoom = 1.0;
  230.     coord->ib.block = 1;
  231.       }
  232.       coord->ib.zoom = ibzoom;
  233.       /* calculate corners of display in img coords */
  234.       coord->ib.cenX = coord->id.cenX;
  235.       coord->ib.cenY = coord->id.cenY;
  236.       lX = coord->ib.cenX - (coord->buf.cenX * ibzoom);
  237.       rX = coord->ib.cenX +
  238.     (((double)coord->buf.width - coord->buf.cenX) * ibzoom);
  239.       tY = coord->ib.cenY - (coord->buf.cenY * ibzoom);
  240.       bY = coord->ib.cenY +
  241.     (((double)coord->buf.height - coord->buf.cenY) * ibzoom);
  242.     }
  243.     /* shift center if buffer extends beyond an edge */
  244.     if( lX < 0.0 ) {
  245.       diff = -lX;
  246.       lX = 0.0;
  247.       rX += diff;
  248.       coord->ib.cenX += diff;
  249.     } else if( rX > (double)coord->img.width ) {
  250.       diff = rX - (double)coord->img.width;
  251.       lX -= diff;
  252.       rX = (double)coord->img.width;
  253.       coord->ib.cenX -= diff;
  254.     }
  255.     if( tY < 0 ) {
  256.       diff = -tY;
  257.       tY = 0;
  258.       bY += diff;
  259.       coord->ib.cenY += diff;
  260.     } else if( bY > (double)coord->img.height ) {
  261.       diff = bY - (double)coord->img.height;
  262.       tY -= diff;
  263.       bY = (double)coord->img.height;
  264.       coord->ib.cenY -= diff;
  265.     }
  266.     /* set edges to integer pixel coords, rounding in from edge */
  267.     coord->ib.srcX1 = (int)(lX + 0.001);
  268.     coord->ib.srcY1 = (int)(tY + 0.001);
  269.     coord->ib.srcX2 = (int)(rX - 0.001);
  270.     coord->ib.srcY2 = (int)(bY - 0.001);
  271.     /* compute transforms */
  272.     set_transform(coord->ib.cenX, coord->ib.cenY, coord->ib.zoom,
  273.           &coord->buf, &coord->img,
  274.           &coord->buftoimg, &coord->imgtobuf);
  275.     combine_transform(&coord->buftofile, &coord->buftoimg, &coord->imgtofile);
  276.     set_edges(&coord->buftofile, &coord->file, &coord->buf, &coord->fb);
  277.     /* compute inverse of buftofile (used to stuff pixels from socket) */
  278.     invert_transform(&coord->filetobuf, &coord->buftofile, coord->file.ioff); 
  279.   }
  280. }
  281.  
  282. /*
  283.  * Subroutine:    set_edges
  284.  * Purpose:    Set up parameter to map image data from src (A) to dst (B)
  285.  *        Set up the edges of dst sys (B) as plotted in src (A)
  286.  * Note:    Used to set up transfer of image data from A to B
  287.  */
  288. void set_edges ( BAtrans, Asys, Bsys, ABmap )
  289.      Transform *BAtrans;
  290.      Coordsys *Asys, *Bsys;
  291.      Edges *ABmap;
  292. {
  293.   float lX, tY, rX, bY, temp;
  294.   float BAzoom;
  295.   void d_transform();
  296.  
  297.   /* compute four corner pixel coords */
  298.   d_transform(BAtrans, Bsys->X1, Bsys->Y1, &lX, &tY);
  299.   d_transform(BAtrans, Bsys->X2, Bsys->Y2, &rX, &bY);
  300.   /* account for any rotation or inversion */
  301.   if( lX > rX ) {
  302.     temp = lX;
  303.     lX = rX;
  304.     rX = temp;
  305.   }
  306.   if( tY > bY ) {
  307.     temp = tY;
  308.     tY = bY;
  309.     bY = temp;
  310.   }
  311.   /* clip AB area by src (A) area */
  312.   ABmap->clip = 0;
  313.   if( lX < Asys->X1 ) {
  314.     lX = Asys->X1;
  315.     ABmap->clip += LX;
  316.   }
  317.   if( rX > Asys->X2 ) {
  318.     rX = Asys->X2;
  319.     ABmap->clip += RX;
  320.   }
  321.   if( tY < Asys->Y1 ) {
  322.     tY = Asys->Y1;
  323.     ABmap->clip += TY;
  324.   }
  325.   if( bY > Asys->Y2 ) {
  326.     bY = Asys->Y2;
  327.     ABmap->clip += BY;
  328.   }
  329.   /* round any edges inward */
  330.   ABmap->srcX1 = (int)(lX + 0.001);
  331.   ABmap->srcY1 = (int)(tY + 0.001);
  332.   ABmap->srcX2 = (int)(rX - 0.001);
  333.   ABmap->srcY2 = (int)(bY - 0.001);
  334.   ABmap->srcXwdth = (int)(0.0001 + rX - lX);
  335.   ABmap->srcYhght = (int)(0.0001 + bY - tY);
  336.   /* get AB block and integer block code (opposite of BA) */
  337.   /* assume symetric orthogonal blocking - one factor is 0, other is block */
  338.   if( BAtrans->inx_outx > 0.000001 )
  339.     BAzoom = BAtrans->inx_outx;
  340.   else if( BAtrans->inx_outx < -0.000001 )
  341.     BAzoom = -BAtrans->inx_outx;
  342.   else if( BAtrans->iny_outx > 0.000001 )
  343.     BAzoom = BAtrans->iny_outx;
  344.   else
  345.     BAzoom = -BAtrans->iny_outx;
  346.   /* block code is integer factor (-1/block for fractional block) */
  347.   /* block is inverse of zoom in our usage of zoom */
  348.   ABmap->zoom = 1.0 / BAzoom;
  349.   if( BAzoom > 0.75 )
  350.     ABmap->block = (int)(BAzoom + 0.5);
  351.   else
  352.     ABmap->block = -(int)(ABmap->zoom + 0.5);
  353.   /* transfer basic mapping destination parameters */
  354.   ABmap->dstX1 = Bsys->X1i;
  355.   ABmap->dstY1 = Bsys->Y1i;
  356.   ABmap->dstX2 = Bsys->X2i;
  357.   ABmap->dstY2 = Bsys->Y2i;
  358.   ABmap->dstXwdth = Bsys->Xwdth;
  359.   ABmap->dstYhght = Bsys->Yhght;
  360. }
  361.